package exceptions;

import bean.response.ResponseBean;
import bean.response.ResultEnum;
import org.apache.shiro.authz.UnauthenticatedException;
import utils.ResultInfoUtil;
import org.apache.catalina.connector.ClientAbortException;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.xmlbeans.impl.piccolo.util.DuplicateKeyException;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.naming.SizeLimitExceededException;
import java.util.Objects;


/**
 *
 * @author Seven
 * @date 2021/11/21
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 拦截Valid校验的报错
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResponseBean notValidException(MethodArgumentNotValidException e){
        BindingResult bindingResult = e.getBindingResult();
        Objects.requireNonNull(bindingResult.getFieldError());
        return ResultInfoUtil.buildError(ResultEnum.BIND_ERROR, bindingResult.getFieldError().getField()+" "+bindingResult.getFieldError().getDefaultMessage());
    }

    @ExceptionHandler(AuthorizationException.class)
    @ResponseBody
    public ResponseBean noAuthorizationException(AuthorizationException e){
        return ResultInfoUtil.buildError(ResultEnum.BAD_REQUEST,"用户未登录或权限不够");
    }

    @ExceptionHandler(UnauthenticatedException.class)
    @ResponseBody
    public ResponseBean noAuthorizationException(UnauthenticatedException e){
        return ResultInfoUtil.buildError(ResultEnum.BAD_REQUEST,"用户未登录");
    }

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public ResponseBean notIllegalArgumentException(IllegalArgumentException e){
        System.out.println("notIllegalArgumentException");
        return  ResultInfoUtil.buildError(ResultEnum.ERROR, e.getMessage());
    }

    @ExceptionHandler(RedisSystemException.class)
    @ResponseBody
    public ResponseBean notRedisSystemException(RedisSystemException e){
        System.out.println("Exception notRedisSystemException");
        return ResultInfoUtil.buildError(ResultEnum.ERROR, "redis system is wrong");
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseBean handlerGlobalException(Exception e){
        return ResultInfoUtil.buildError(ResultEnum.BIND_ERROR, e.toString());
    }

    @ExceptionHandler(SizeLimitExceededException.class)
    @ResponseBody
    public ResponseBean noSizeLimitExceededException(SizeLimitExceededException e){
        return ResultInfoUtil.buildError(ResultEnum.ERROR, e.toString());
    }

    /**
     * 数组越界 请求数据不合法
     * @param e
     * @return
     */
    @ExceptionHandler(ArrayIndexOutOfBoundsException.class)
    @ResponseBody
    public ResponseBean noArrayIndexOutOfBoundsException(ArrayIndexOutOfBoundsException e){
        return ResultInfoUtil.buildError(ResultEnum.ERROR, e.toString());
    }

    /**
     * 数据库插入时，违反唯一性约束
     * @param e
     * @return
     */
    @ExceptionHandler(DuplicateKeyException.class)
    @ResponseBody
    public ResponseBean noDuplicateKeyException(DuplicateKeyException e){
        return ResultInfoUtil.buildError(ResultEnum.ERROR, e.toString());
    }

    /**
     * 插入数据时，该数据没有默认值或未给值
     * @param e
     * @return
     */
    @ExceptionHandler(DataIntegrityViolationException.class)
    @ResponseBody
    public ResponseBean noDataIntegrityViolationException(DataIntegrityViolationException e){
        return ResultInfoUtil.buildError(ResultEnum.ERROR, e.toString());
    }

    /**
     * 插入数据时，数据库类型和对象类型不统一
     * @param e
     * @return
     */
    @ExceptionHandler(MyBatisSystemException.class)
    @ResponseBody
    public ResponseBean noMyBatisSystemException(MyBatisSystemException e){
        return ResultInfoUtil.buildError(ResultEnum.ERROR, e.toString());
    }

    /**
     * 连接时间较短，中断，或网络原因
     * @param e
     * @return
     */
    @ExceptionHandler(ClientAbortException.class)
    @ResponseBody
    public ResponseBean noClientAbortException(ClientAbortException e){
        return ResultInfoUtil.buildError(ResultEnum.ERROR, e.toString());
    }

    /**
     * 格式转换异常
     * @param e
     * @return
     */
    @ExceptionHandler(NumberFormatException.class)
    @ResponseBody
    public ResponseBean noNumberFormatException(NumberFormatException e){
        return ResultInfoUtil.buildError(ResultEnum.ERROR, e.toString());
    }

//    PacketTooBigException 视频上传，文件过大
//    MyBatisSystemException 插入数据时，数据库类型和对象类型不统一 WrongArgumentException
//    RedisConnectionFailureException 无法连接redis

}
